%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%  Copyright by Wenliang Du                                        %%
%%  This work is licensed under the Creative Commons                %%
%%  Attribution-NonCommercial-ShareAlike 4.0 International License. %%
%%  To view a copy of this license, visit                           %%
%%  http://creativecommons.org/licenses/by-nc-sa/4.0/.              %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newcommand{\commonfolder}{../../common-files}

\input{\commonfolder/header}
\input{\commonfolder/copyright}
\hypersetup{%
    pdfborder = {0 0 0}
}

\lhead{\bfseries SEED Labs -- Blockchain Exploration Lab}

\begin{document}

\begin{center}
{\LARGE Blockchain Exploration Lab}
\end{center}

\seedlabcopyright{2023}



% *******************************************
% SECTION
% ******************************************* 
\section{Overview}

The objective of this lab is to help students gain some hands-on experiences
with blockchains, in particular, with the Ethereum blockchain. 
A blockchain system is quite complicated, and it is hard to cover every aspect
of it in a single lab. We have developed a series of labs focusing 
on this new technology. This lab is the first one in this 
series, with a goal of getting students to become familiar with the platform. 
Students will use existing tools and implement their own tools
to interact with the Ethereum blockchain. 
The following topics are covered in this lab:

\begin{itemize}[noitemsep]
\item MetaMask, wallet, account 
\item Transactions and blocks, sending transactions 
\item Ethereum nodes 
\end{itemize}


\paragraph{Lab environment.} The activities in this document 
have been tested on our pre-built
Ubuntu 20.04 VM, which can be downloaded from the SEED website.  


% *******************************************
% SECTION
% *******************************************
\section{Lab Setup: Starting the Blockchain Emulator} 

This lab will be performed inside the SEED Internet Emulator (simply
called the emulator in this document). If this is the first time you
use the emulator, it is important that you read this section.
We recommend instructors to provide a lab session to
help students get familiar with the emulator.

\input{../common-files/emulator.tex}


\paragraph{EtherView.} 
\input{../common-files/etherview.tex}



% *******************************************
% SECTION
% *******************************************
\section{Task 1: Setting Up MetaMask Wallet} 

There are many ways to interact with the blockchain. 
For the basic operations, we can use a wallet application, which
manages our keys, displays the balances of our accounts, 
and sends and receives transactions.
MetaMask is a very popular wallet application for the 
Ethereum blockchain. It is available as a browser extension
or a standalone mobile application. 
In this lab, we will use the browser extension.


\paragraph{Task 1.a. Installing the MetaMask extension.} 
Inside the virtual machine, go to Firefox's menu, 
click the \texttt{"Add-ons and themes"}
item. Search for \texttt{metamask}, and you will find 
an extension developed by \texttt{danfinlay}. 
Follow the instruction to install it. Take a screenshot 
to show that you have successfully installed the 
extension. 


\paragraph{Task 1.b. Connecting to the Blockchain.} 
We need to connect the MetaMask wallet to our blockchain. 
This is done via connecting MetaMask to one of the 
nodes on the blockchain. We can find the IP addresses of all
the Ethereum nodes using the \texttt{"docker ps"} command. We have 
appended the IP address to the container name (the actual IP
address you get from your emulator may be different from
those listed in the following).

\begin{lstlisting}
$ dockps | grep Eth
e372096bb926  as150h-Ethereum-POA-00-Signer-BootNode-10.150.0.71
f0ef91ef9e22  as150h-Ethereum-POA-01-10.150.0.72
3b8c1d191058  as151h-Ethereum-POA-02-Signer-10.151.0.71
...
aea1106d932d  as164h-Ethereum-POA-18-Signer-BootNode-10.164.0.71
7cd6fa6888b2  as164h-Ethereum-POA-19-10.164.0.72
\end{lstlisting}
 

Pick one of the nodes, and then configure MetaMask to connect to
this node. Go to the \texttt{Settings} menu inside MetaMask
and follow the instructions below. Replace 
the \texttt{<IP Address>} with the actual IP address of the 
node that you have selected. Take a screenshot to show that 
you have successfully connected to the emulator. 

\begin{lstlisting}
Settings > Security & privacy > Add custom network > + Add a custom network

Network name:    pick any name (e.g., SEED emulator)
New RPC URL:     http://<IP Address>:8545 
Chain ID:        1337
Currency symbol: ETH
\end{lstlisting}



\paragraph{Task 1.c. Adding accounts.} 
In this task, we will add a few accounts to our wallet. We can ask
MetaMask to create new accounts for us or import existing 
accounts. We have already created several accounts when creating the 
emulator, and these accounts already have funds in them. 
These accounts are generated from the following mnemonic phrase,
so they can be recovered using the same phrase. 

\begin{lstlisting}
gentle always fun glass foster produce north tail security list example gain
\end{lstlisting}

In this task, we will add these existing accounts to our 
MetaMask wallet, so we can use them to send transactions. 
To do that, we need to log out from our MetaMask account (or lock our 
account). That will lead us to the login window. We will pretend 
that we have forgotten the password, so we will click the 
\texttt{"Forgot password"} link. 
For MetaMask, if you forget the password to your wallet account, 
unless you have 
already stored your keys somewhere, the only way to get your account
keys back is through a secret recovery phrase. 
By typing the above recovery phrase, we can ask MetaMask to recover
our keys. 

MetaMask will generate all the existing accounts that have a non-zero 
balance on the blockchain. Please show the balance of these accounts in your 
lab report. 
If you do not see the conversion of ETH to fiat currency (such as dollars),
you can go to \texttt{Settings > Advanced} and enable the 
\texttt{"Show conversion on test networks"}. MetaMask will now 
show the conversion. 

 
\paragraph{Task 1.d. Sending transactions.} 
Now we can send transactions using our accounts. Please 
send money from one account to another, and 
check the balance of these accounts to verify
that the transaction is successful. 
Please provide the screenshots for the entire process. 
Please also show the 
details of transactions using \texttt{EtherView}, and 
verify that the transaction details are consistent with
what you have sent. 



% *******************************************
% SECTION
% *******************************************
\section{Task 2: Interacting with Blockchain Using Python} 

We have already seen to interact with the blockchain 
using an existing tool like MetaMask. In this task, we will write our 
own tool to interact with the blockchain. 
This will give us more insight on how to interact with 
a blockchain. We will conduct this task from the host VM. 
The code used in this task can be found at the \path{Labsetup/Files} folder. 


\paragraph{Task 2.a: Installing Python modules.} 
We will use the \texttt{web3} and \texttt{docker} modules
in our Python program. We need to install these modules using the following 
command (they may have already been installed in your VM). 
It should be noted that our code uses an older
version of \texttt{web3}. That is why we 
have specified the version number in our command. 

\begin{lstlisting}
pip3 install web3==5.31.1 docker
\end{lstlisting}


\paragraph{Task 2.b: Checking account balance.} 
The code (provided) below shows how to get a balance from the blockchain.
Please go to your MetaMask wallet, get the first three accounts,
and then use the following program to check their balances.
Compare the values with what you see in MetaMask. 

\begin{lstlisting}[caption=Get balance (\texttt{web3\_balance.py}), language=python] 
#!/bin/env python3
from web3 import Web3

url  = 'http://10.150.0.71:8545'
web3 = Web3(Web3.HTTPProvider(url))  # Connect to a blockchain node

addr = Web3.toChecksumAddress('0xF5406927254d2dA7F7c28A61191e3Ff1f2400fe9')
balance = web3.eth.get_balance(addr) # Get the balance 
print(addr + ": " + str(Web3.fromWei(balance, 'ether')) + " ETH")
\end{lstlisting}
 

\paragraph{Task 2.c: Sending transactions.} 
In this task, we will use a Python program to send out a transaction. 
This program constructs a transaction, signs it using the sender's
private key, and then sends out the transaction via an Ethereum node.
The program will block, waiting for the transactions to be 
confirmed (i.e., to be included in a block). Run this program,
and then check from MetaMask whether the balance of the sender/receiver
accounts have changed. You should fill in the needed information
in Lines \lineone, \linetwo, and \linethree. For the private key,
you can get it from MetaMask: click the \texttt{"Account details"}
menu, and then click the \texttt{"Show private key"} button.


\begin{lstlisting}[caption=Send transaction (\texttt{web3\_raw\_tx.py}), language=python]
from web3 import Web3
from eth_account import Account

web3 = Web3(Web3.HTTPProvider('http://ip-address:8545'))             (*@\lineone@*) 

# Sender's private key
key = 'replace this with the actual private key'                     (*@\linetwo@*) 
sender = Account.from_key(key)

recipient = Web3.toChecksumAddress('replace this with an account #') (*@\linethree@*) 
tx = {
  'chainId':  1337,
  'nonce':    web3.eth.getTransactionCount(sender.address),
  'from':     sender.address,
  'to':       recipient,
  'value':    Web3.toWei("11", 'ether'),
  'gas':      200000,
  'maxFeePerGas':         Web3.toWei('4', 'gwei'),
  'maxPriorityFeePerGas': Web3.toWei('3', 'gwei'),
  'data':     ''
}

# Sign the transaction and send it out
signed_tx  = web3.eth.account.sign_transaction(tx, sender.key)
tx_hash    = web3.eth.sendRawTransaction(signed_tx.rawTransaction)

# Wait for the transaction to appear on the blockchain
tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
print("Transaction Receipt: {}".format(tx_receipt))
\end{lstlisting}


% *******************************************
% SECTION
% *******************************************
\section{Task 3: Interacting with Blockchain Using Geth} 

We can also interact with the blockchain directly from 
a blockchain node. 
In our emulator, each Ethereum node runs the Geth (go-ethereum) client, which is 
a Go implementation of Ethereum. 
There are multiple ways to interact with the Geth client, including websockets,
HTTP, and local IPC. When we interact with the Geth nodes 
using MetaMask or Python programs, we are using the JSON-RPC method. 
We can also log into a Geth node, and communicate with
it using local IPC. The following \texttt{geth} command
gets an interactive console on the node. 


\begin{lstlisting}
root@f6fb88f9e09d / # geth attach
Welcome to the Geth JavaScript console!

instance: Geth/NODE_8/v1.10.26-stable-e5eb32ac/linux-amd64/go1.18.10
coinbase: 0xa888497f7938825f80f35867a1e707f42b9b347d
...
To exit, press ctrl-d
>
\end{lstlisting}

This is an interactive JavaScript console, so we can run JavaScript code
in it. The \texttt{eth} class has many APIs that we can use
to interact with the blockchain. 
The following example shows
how to get an account balance. 

\begin{lstlisting}
> myaccount = "0xc20ab9a1ab88c9fae8305b302836ee7734c6afbe"
> eth.getBalance(myaccount)
100000000
\end{lstlisting}

\paragraph{Task 3.a: Getting balance.} 
Please get the balances for the first 3 accounts in your MetaMask
wallet, and see whether they are the same as the one shown on MetaMask.


\paragraph{Task 3.b: Sending transactions.} 
Each node maintains a list of accounts, which are
stored in \path{/root/.ethereum/keystore}.
Their address are loaded into the \texttt{eth.accounts[]} array.
For example, to get the first account address, we can use 
\texttt{eth.accounts[0]}. 
These accounts are locked (i.e., encrypted using a password), 
so to use them to send transactions, we need to unlock it using
the password. In our emulator, all the accounts are locked using
the hardcoded password \texttt{admin}. 


\begin{lstlisting}
> eth.accounts
["0x3e64b5b296ccb365eab980b094a4af7b1009825e"]
> personal.unlockAccount(eth.accounts[0], "admin")
true
\end{lstlisting}

Now, we can send fund from these accounts to an account in our 
MetaMask wallet. Please use the following example to send fund to
one of your MetaMask wallet accounts, and see whether the results
show up correctly on MetaMask. 

\begin{lstlisting}
> sender = eth.accounts[0]
> target = "0xF5406927254d2dA7F7c28A61191e3Ff1f2400fe9"
> amount =  web3.toWei(0.2, "ether")
> eth.sendTransaction ({from: sender, to: target, value: amount})
"0x8c6c57d5a32de...7304"
\end{lstlisting}
 

\paragraph{Task 3.c: Sending transactions from a different account.} 
Instead of using \texttt{eth.accounts[0]}, let us use an account from our 
MetaMask wallet, i.e., we set \texttt{sender} to one of the accounts in our 
wallet. Try send a transaction and report/explain your observation. 


% *******************************************
% SECTION
% *******************************************
\section{Task 4: Adding a Full Node} 

In this task, we will learn how to join an existing blockchain network.
We have already provided an empty container, with 
word \texttt{new\_eth\_node} encoded in its name. 
Your job is to configure this container, turning it into an Ethereum node. 
First, we initialize our node using the blockchain information,
which is captured in its genesis block. 
A genesis block is the first block of a block chain. You can get a copy
of the genesis block from an existing Ethereum node (in \texttt{/tmp/eth-genesis.json}).  

\begin{lstlisting}
geth --datadir /root/.ethereum init /eth-genesis.json
\end{lstlisting}

Second, we run the \texttt{geth} command to join 
an existing blockchain network. To do that, 
we need to provide a list of bootnodes. Go to any of 
existing Ethereum nodes (non-bootnode), you should be able to 
see a file called \texttt{eth-node-urls} in the \texttt{/tmp}
folder. This file contains a list of the bootnodes on the blockchain
network. Copy and paste its content to the \texttt{/tmp/eth-node-urls}
file in the \texttt{new\_eth\_node} container. 
In the following \texttt{geth} command, we feed
the content of the \texttt{/tmp/eth-node-urls} file 
to the \texttt{bootnodes} option.

\begin{lstlisting}[caption=\texttt{start.sh}]
geth --datadir /root/.ethereum --identity="NEW_NODE_01" --networkid=1337 \
     --syncmode full --snapshot=False --verbosity=2  --port 30303 \
     --bootnodes "$(cat /tmp/eth-node-urls)" --allow-insecure-unlock \      
     --http --http.addr 0.0.0.0 --http.corsdomain "*" \
     --http.api web3,eth,debug,personal,net,clique,engine,admin,txpool
\end{lstlisting}


\paragraph{Task.} Please follow the instructions above to 
turn the \texttt{new\_eth\_node} container into an Ethereum node. 
After setting it up, please do the following tasks: 

\begin{itemize}
\item Run \texttt{"geth attach"} on this node to get the JavaScript console;
use \texttt{admin.peers} to see the peers of the node.  

\item In the same console, 
use \texttt{personal.newAccount()} to create an new account on this node. 
We call it Account Z. 

\item Modify the Python code (\texttt{web3\_raw\_tx.py}) from Task 2, so it 
connects to this new node, and use this new node to send transactions. 
Send some amount of ethers to Account Z. 

\item In the JavaScript console, send a transaction
from Account Z to another account. 
\end{itemize}
 

% *******************************************
% SECTION
% ******************************************* 
\section{Submission}

\seedsubmission


\end{document}



